class Watcher {
    constructor(expr, vm, callback) {
        //* 存储参数
        this.expr = expr;
        this.vm = vm;
        this.callback = callback;
        //* 存储旧值
        this.oldValue = this.getOldValue();
    }
    getOldValue() {
        Dep.target = this;
        //* 获取旧值,触发每个属性上的get方法,保存watcher
        const oldVal = compileUtil.getValue(this.expr, this.vm);
        //* Dep.target是全局变量,是数据和视图的桥梁,必须保证唯一
        Dep.target = null;
        return oldVal;
    }
    update() {
        //* 获取新值
        const newVal = compileUtil.getValue(this.expr, this.vm);
        if (newVal !== this.oldValue) {
            //* 触发回调函数,更新视图
            this.callback(newVal);
        }
    }
}
class Dep {
    constructor() {
            this.sub = [];
        }
        //* 收集观察者
    addWatcher(watcher) {
            this.sub.push(watcher);
        }
        //* 通知观察者去更新
    notify() {
        this.sub.forEach((w) => {
            w.update();
        });
    }
}
class Observer {
    constructor(data) {
        //* 接受传入的data,调用observer方法
        this.observer(data);
    }
    observer(data) {
        if (data && typeof data === "object") {
            //* 遍历data每个属性,调用defineReactive进行数据劫持
            Object.keys(data).forEach((key) => {
                this.defineReactive(data, key, data[key]);
            });
        }
    }
    defineReactive(obj, key, value) {
        //* 处理嵌套,使用递归
        if (value && typeof value === "object") {
            this.observer(value);
        }
        //* 对每个data上的属性实例化一个dep,以保存watcher
        const dep = new Dep();
        Object.defineProperty(obj, key, {
            enumerable: true,
            configurable: false,
            get() {
                //* 每一个dep储存watcher
                Dep.target && dep.addWatcher(Dep.target);
                //* 如果有更新,则这里的value是set修改过的
                return value;
            },
            set: (newValue) => {
                this.observer(newValue);
                //* 此处修改的是definedReactive传入的value的值,在get访问器作用时,修改返回的value
                if (newValue !== value) {
                    value = newValue;
                    //* 此时vm.$data的值改变了,但视图还没有改变,需要调用watcher上的方法改变Dom属性
                    //* 通知watcher更新视图
                    dep.notify();
                }
            },
        });
    }
}

// function defineReactive(obj, key, value) {
//   Object.defineProperty(obj, key, {
//     enumerable: true,
//     configurable: false,
//     get() {
//       return value;
//     },
//     set: (newValue) => {
//       if (newValue !== value) {
//         value = "test";
//       }
//     },
//   });
// }
// const obj = {
//   name: "wang",
// };
// defineReactive(obj, "name", "wang");
// obj.name = "ddfdasdfa";
// console.log(obj.name);